/*
 * Copyright 2011 kubtek <kubtek@mail.com>
 * Copyright 2025 Hu Zheng <huzheng_001@hotmail.com>
 *
 * This file is part of StarDict.
 *
 * StarDict is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * StarDict is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with StarDict.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "parsedata_wordnet.h"
#include "../../lib/parsedata.h"
#include <cstring>
#include <glib/gi18n.h>
#include <list>

#ifdef _WIN32
#include <windows.h>
#endif


struct WnUserData {
	const gchar *oword;
	std::string type;
	std::list<std::string> wordlist;
	std::string gloss;
};

static void func_parse_text(GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **error)
{
	const gchar *element = g_markup_parse_context_get_element(context);
	if (!element)
		return;
	WnUserData *Data = (WnUserData *)user_data;
	if (strcmp(element, "type")==0) {
		Data->type.assign(text, text_len);
	} else if (strcmp(element, "word")==0) {
		std::string word(text, text_len);
		if (word != Data->oword) {
			Data->wordlist.push_back(word);
		}
	} else if (strcmp(element, "gloss")==0) {
		Data->gloss.assign(text, text_len);
	}
}

static void wordnet2result(const char *p, size_t sec_size, ParseResult &result, const char *oword)
{
	WnUserData Data;
	Data.oword = oword;
	GMarkupParser parser;
	parser.start_element = NULL;
	parser.end_element = NULL;
	parser.text = func_parse_text;
	parser.passthrough = NULL;
	parser.error = NULL;
	GMarkupParseContext* context = g_markup_parse_context_new(&parser, (GMarkupParseFlags)0, &Data, NULL);
	g_markup_parse_context_parse(context, p, sec_size, NULL);
	g_markup_parse_context_end_parse(context, NULL);
	g_markup_parse_context_free(context);

	std::string res;
	char *eword;
	if (Data.type == "n") {
		res += "Noun\n";
	} else if (Data.type == "v") {
		res += "Verb\n";
	} else if (Data.type == "a") {
		res += "Adjective\n";
	} else if (Data.type == "s") {
		res += "Adjective satellite\n";
	} else if (Data.type == "r") {
		res += "Adverb\n";
	} else {
		eword = g_markup_escape_text(Data.type.c_str(), Data.type.length());
		res += eword;
		g_free(eword);
	}
	for (std::list<std::string>::iterator i = Data.wordlist.begin(); i != Data.wordlist.end(); ++i) {
		if (i != Data.wordlist.begin()) {
			res += '\t';
		}
		res += "<span foreground=\"blue\" underline=\"single\">";
		eword = g_markup_escape_text(i->c_str(), i->length());
		res += eword;
		g_free(eword);
		res += "</span>";
	}
	if (!Data.wordlist.empty()) {
		res += '\n';
	}
	eword = g_markup_escape_text(Data.gloss.c_str(), Data.gloss.length());
	res += eword;
	g_free(eword);
	ParseResultItem item;
	item.type = ParseResultItemType_mark;
	item.mark = new ParseResultMarkItem;
	item.mark->pango = res;
	result.item_list.push_back(item);
}

std::string wordnet2pango(const char *p, guint32 sec_size, const char *oword)
{
	ParseResult result;
	wordnet2result(p, sec_size, result, oword);
	std::string markup_str;
	for (std::list<ParseResultItem>::iterator it = result.item_list.begin(); it != result.item_list.end(); ++it) {
		switch (it->type) {
			case ParseResultItemType_mark:
				markup_str += it->mark->pango;
				break;
			default:
				g_warning("Unsupported item type.");
				break;
		}
	}
	return markup_str;
}


